spb/satelliteindex
Public
TypeScript 66.5%
Python 30.9%
JavaScript 1.4%
CSS 0.7%
1import { NextResponse } from 'next/server';2import type { ReviewDecision } from '@/components/admin/types';3import { adminApi, AdminApiError } from '@/lib/admin-api';4import { isAdmin } from '@/lib/admin-auth';56export const dynamic = 'force-dynamic';78const DECISIONS: ReviewDecision[] = ['merged', 'kept_separate', 'dismissed'];910/** Entity-resolution decision: body `{ "decision": "merged" | "kept_separate" | "dismissed" }`. Merges are audited server-side (entity_merges). */11export async function POST(req: Request, ctx: { params: Promise<{ id: string }> }): Promise<Response> {12 if (!(await isAdmin())) return NextResponse.json({ error: { title: 'Unauthorized', status: 401 } }, { status: 401 });13 const { id } = await ctx.params;14 const itemId = Number(id);15 const body = (await req.json().catch(() => null)) as { decision?: unknown } | null;16 const decision = body?.decision;17 if (!Number.isInteger(itemId) || typeof decision !== 'string' || !DECISIONS.includes(decision as ReviewDecision)) {18 return NextResponse.json({ error: { title: 'Invalid request', detail: 'decision must be merged | kept_separate | dismissed', status: 422 } }, { status: 422 });19 }20 try {21 const out = await adminApi.decide(itemId, decision as ReviewDecision, 'admin-web');22 return NextResponse.json(out.data);23 } catch (e) {24 const status = e instanceof AdminApiError && e.status > 0 ? e.status : 502;25 return NextResponse.json({ error: { title: 'Decision failed', detail: (e as Error).message, status } }, { status });26 }27}28